package cn.kgc.reflect;

import javax.lang.model.element.VariableElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @Author: 课工场
 * @Version: v1.0  2023/2/14
 * @Description:  反射的基本使用
 * 什么是反射?  动态性
 *  在程序运行的过程中，通过编码的方式解析类中的属性，方法，构造方法,注解等以及完成相关操作的过程
 *
 *  1.使用反射 第一步  获取类对象   .java  -> public  class  Student{ }  Class   studentClass
 *      1. 类名.class      Class   studentClass   = Student.class
 *      2. 对象名.getClass()  Student student = new Student()      Class   studentClass  = student.getClass()
 *      3. Class.forName("类全限定名")  -> 驱动   Class.forName("com.mysql.jdbc.Driver")    new Driver()  推荐
 *
 *  2.解析  构造   属性   方法
 *
 *
 *  3.相关操作  属性 -> 获取值  赋值    构造 ->创建对象  方法 ->调用
 *

 */
public class TestReflect {


    public static void main(String[] args) {

        test03();

    }

    // 使用反射操作构造方法
    public static void  test01(){
        //Class clazz = Person.class;  类名.class

        //Person person = new Person();
        //Class clazz = person.getClass();  对象名.getClass()


        try {
            // 获取一个 Person的类对象
            Class  clazz = Class.forName("cn.kgc.reflect.Person");

            // 构造方法  getConstructors()  获取所有的被public修饰的构造方法  Constructor
            Constructor[] constructors = clazz.getConstructors();
            for (Constructor constructor : constructors) {
                System.out.println("constructor = " + constructor);
            }

            System.out.println("------------------------------");

            //  获取所有的构造方法
            Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
            for (Constructor declaredConstructor : declaredConstructors) {
                System.out.println("declaredConstructor = " + declaredConstructor);
            }

            System.out.println("------------------------------");
            //获取无参构造
            Constructor constructor = clazz.getConstructor();
            System.out.println("constructor = " + constructor);


            System.out.println("------------------------------");

            //Constructor constructor1 = clazz.getConstructor(Integer.class, String.class);

            Constructor constructor1 =  clazz.getDeclaredConstructor(Integer.class, String.class);
            System.out.println("constructor1 = " + constructor1);

            // 创建对象  私有的构造 创建对象 取消权限修饰符的限制  暴力反射
            constructor1.setAccessible(true);

            Person person = (Person) constructor1.newInstance(1, "tom");
            System.out.println("person = " + person);

        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    // 使用反射解析类对象中的属性
    public static void  test02(){


        try {
            Class clazz = Class.forName("cn.kgc.reflect.Person");
            // 解析的属性  被封装成  Field  public
            Field[] fields = clazz.getFields();
            for (Field field : fields) {
                System.out.println("field = " + field);
            }

            System.out.println("-----------------------");
            //获取以声明的属性
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                System.out.println("declaredField = " + declaredField);
            }

            System.out.println("-----------------------");

            Field id = clazz.getField("id");
            System.out.println("id = " + id);

            Field field = clazz.getDeclaredField("name");
            System.out.println("name = " + field);

            // 操作  赋值 取值  参数1  ： 对象  参数2  属性值
            Person person = new Person();
            System.out.println("person = " + person);

            field.setAccessible(true);
            field.set(person,"tom");
            System.out.println("person = " + person);

            Object o = field.get(person);
            System.out.println("o = " + o);


        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    //使用反射解析类对象中的方法
    public static void  test03(){

        try {
            Class clazz = Class.forName("cn.kgc.reflect.Person");

            // 解析方法

            Method[] declaredMethods = clazz.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                System.out.println("declaredMethod = " + declaredMethod);
            }

            // 获取指定的方法
            Method method = clazz.getDeclaredMethod("test01");
            method.setAccessible(true);

            Person person = new Person();

            // 实现方法的调用
            Object invoke = method.invoke(person);
            System.out.println("invoke = " + invoke);


        } catch (Exception e) {
            e.printStackTrace();
        }


    }


}
